﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../impl/head.h"
#include "../macro/head.h"
#include "mem_alloc.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 

namespace xos_common
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static mem_alloc::POOL * pool_ptr = 0;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//

	mem_alloc::mem_alloc()
	{
		m_nPropSize = 32;
	}

	mem_alloc::~mem_alloc()
	{
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 
	// 分配内存
	// 

	void * mem_alloc::malloc_from_big_buf( int nSize )
	{
		using namespace std;

		xos_box::i_big_buf * pBigBuf = 0;
		char * pCharBufAddr = 0;
		char * lpszBuf = 0;
		void * lpData = 0;
		xos::xos_u8 type = 0;
		int ret = 0;

		if( 0 == ret )
		{
			ret = g_pSysData->m_pContainer->box()->create( xos_box::enumObj::BOX_OBJ_BIG_BUF, (void **)&pBigBuf );
		}

		if( 0 == ret )
		{
			lpszBuf = (char *)pBigBuf->get_data( 0, 0, 0 );
			pCharBufAddr = (char *)pBigBuf;
			type = 2;
		}

		if( 0 == ret )
		{
			xos_box::i_serial & obj = *g_pSysData->m_pContainer->serial();
			int pos = 0, len = 0, nLenLeft = m_nPropSize;
			obj.pack_int8( lpszBuf, pos, &len, &nLenLeft, type );
			pos += len;
			len = 0;
			obj.pack_mem( lpszBuf, pos, &len, &nLenLeft, (char *)&pCharBufAddr, sizeof( pCharBufAddr ) );
		}

		if( 0 == ret )
		{
			lpData = lpszBuf + m_nPropSize;
		}

		return lpData;
	}

	void * mem_alloc::malloc_from_small_buf( int nSize )
	{
		using namespace xos_common;
		using namespace std;

		xos_box::i_buf * pBuf = 0;
		char * pCharBufAddr = 0;
		char * lpszBuf = 0;
		void * lpData = 0;
		xos::xos_u8 type = 0;
		int ret = 0;

		if( 0 == ret )
		{
			ret = g_pSysData->m_pContainer->box()->create( xos_box::enumObj::BOX_OBJ_BUF, (void **)&pBuf );
		}

		if( 0 == ret )
		{
			lpszBuf = (char *)pBuf->get_data( 0, 0, 0 );
			pCharBufAddr = (char *)pBuf;
			type = 1;
		}

		if( 0 == ret )
		{
            xos_box::i_serial & obj = *g_pSysData->m_pContainer->serial();
			int pos = 0, len = 0, nLenLeft = m_nPropSize;
			obj.pack_int8( lpszBuf, pos, &len, &nLenLeft, type );
			pos += len;
			len = 0;
			obj.pack_mem( lpszBuf, pos, &len, &nLenLeft, (char *)&pCharBufAddr, sizeof( pCharBufAddr ) );
		}

		if( 0 == ret )
		{
			lpData = lpszBuf + m_nPropSize;
		}

		return lpData;
	}

	void * mem_alloc::malloc_from_memory( int nSize )
	{
		using namespace xos_common;
		using namespace std;

		char * pCharBufAddr = 0;
		char * lpszBuf = 0;
		void * lpData = 0;
		xos::xos_u8 type = 0;
		int ret = 0;

		if( 0 == ret )
		{
			int nWantSize = nSize + m_nPropSize;
			lpszBuf = new char[nWantSize];
			if( lpszBuf )
			{
				pCharBufAddr = lpszBuf;
				type = 0;
			}
			else
			{
				ret = 1;
			}
		}

		if( 0 == ret )
		{
            xos_box::i_serial & obj = *g_pSysData->m_pContainer->serial();
			int pos = 0, len = 0, nLenLeft = m_nPropSize;
			obj.pack_int8( lpszBuf, pos, &len, &nLenLeft, type );
			pos += len;
			len = 0;
			obj.pack_mem( lpszBuf, pos, &len, &nLenLeft, (char *)&pCharBufAddr, sizeof( pCharBufAddr ) );
		}

		if( 0 == ret )
		{
			lpData = lpszBuf + m_nPropSize;
		}

		return lpData;
	}

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 
	// 提供给7z的分配内存函数
	// 

	void * mem_alloc::my_malloc( size_t size )
	{
		using namespace xos_common;
		using namespace std;
		int ret = 0;

		void * lpRetAddr = 0;
        int nSize = (int)size;

		if( size > (size_t)( xos_box::i_big_buf::BUF_SIZE - m_nPropSize ) )
		{
			lpRetAddr = malloc_from_memory( nSize );
		}
		else if( size > (size_t)( xos_box::i_buf::BUF_SIZE - m_nPropSize ) )
		{
			lpRetAddr = malloc_from_big_buf( nSize );
		}
		else if( size > 0 )
		{
			lpRetAddr = malloc_from_small_buf( nSize );
		}
		else
		{
			ret = 1;
		}

		if( 0 == ret )
		{
			//cout << "malloc memory = " << size / 1024 << "K,addr = " << (void *)lpRetAddr << endl;
		}

		return lpRetAddr;
	}

	void mem_alloc::my_free( void * address )
	{
		using namespace xos_common;
		using namespace std;
		int ret = 0;

		char * pAddress = (char *)address;
		char * lpszBuf = (char *)( pAddress - m_nPropSize );
		xos_box::i_buf * pBigBuf = 0;
		xos_box::i_buf * pBuf = 0;

		if( ( 0 == ret ) && !address )
		{
			ret = 1;
		}

		if( 0 == ret )
		{
			//cout << "free addr = " << address << endl;
		}

		if( 0 == ret )
		{
            xos_box::i_serial & obj = *g_pSysData->m_pContainer->serial();
			int pos = 0, len = m_nPropSize;
			xos::xos_u8 u8 = 0;
			obj.un_pack_int8( lpszBuf, &pos, &len, &u8 );
			if( 2 == u8 )
			{
				obj.un_pack_mem( lpszBuf, &pos, &len, (char *)&pBigBuf, sizeof( pBigBuf ), 0, 0 );
				if( pBigBuf )
				{
					pBigBuf->release();
					pBigBuf = 0;
				}
			}
			else if( 1 == u8 )
			{
				obj.un_pack_mem( lpszBuf, &pos, &len, (char *)&pBuf, sizeof( pBuf ), 0, 0 );
				if( pBuf )
				{
					pBuf->release();
					pBuf = 0;
				}
			}
			else
			{
				delete lpszBuf;
				lpszBuf = 0;
			}
		}
	}

	//////////////////////////////////////////////////////////////////////////
	// 

    int mem_alloc::get_addr( POOL *** pppPool, LIST *** pppList )
    {
		int ret = 0;
		if( pppPool )
		{
			*pppPool = &pool_ptr;
		}
		if( pppList )
		{
			*pppList = 0;
		}
		return ret;
    }

	int mem_alloc::init()
	{
		int nRet = 0;
		return nRet;
	}

	int mem_alloc::term()
	{
		int nRet = 0;
		return nRet;
	}

}
